home *** CD-ROM | disk | FTP | other *** search
- #!/bin/sh
- #
- # $Id: rc.apparmor.functions 1280 2008-06-09 11:00:28Z jrjohansen $
- #
- # ----------------------------------------------------------------------
- # Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
- # NOVELL (All rights reserved)
- #
- # This program is free software; you can redistribute it and/or
- # modify it under the terms of version 2 of the GNU General Public
- # License published by the Free Software Foundation.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, contact Novell, Inc.
- # ----------------------------------------------------------------------
- # rc.apparmor.functions by Steve Beattie
- #
- # NOTE: rc.apparmor initscripts that source this file need to implement
- # the following set of functions:
- # aa_action
- # aa_log_action_start
- # aa_log_action_end
- # aa_log_success_msg
- # aa_log_warning_msg
- # aa_log_failure_msg
- # aa_log_skipped_msg
- # aa_log_daemon_msg
- # aa_log_end_msg
-
- # Some nice defines that we use
-
- CONFIG_DIR=/etc/apparmor
- MODULE=apparmor
- OLD_MODULE=subdomain
- if [ -f "${CONFIG_DIR}/${MODULE}.conf" ] ; then
- APPARMOR_CONF="${CONFIG_DIR}/${MODULE}.conf"
- elif [ -f "${CONFIG_DIR}/${OLD_MODULE}.conf" ] ; then
- APPARMOR_CONF="${CONFIG_DIR}/${OLD_MODULE}.conf"
- elif [ -f "/etc/immunix/subdomain.conf" ] ; then
- aa_log_warning_msg "/etc/immunix/subdomain.conf is deprecated, use ${CONFIG_DIR}/subdomain.conf instead"
- APPARMOR_CONF="/etc/immunix/subdomain.conf"
- elif [ -f "/etc/subdomain.conf" ] ; then
- aa_log_warning_msg "/etc/subdomain.conf is deprecated, use ${CONFIG_DIR}/subdomain.conf instead"
- APPARMOR_CONF="/etc/subdomain.conf"
- else
- aa_log_warning_msg "Unable to find config file in ${CONFIG_DIR}, installation problem?"
- fi
-
- # Read configuration options from /etc/subdomain.conf, default is to
- # warn if subdomain won't load.
- SUBDOMAIN_MODULE_PANIC="warn"
- SUBDOMAIN_ENABLE_OWLSM="no"
- APPARMOR_ENABLE_AAEVENTD="no"
-
- if [ -f "${APPARMOR_CONF}" ] ; then
- #parse the conf file to see what we should do
- . "${APPARMOR_CONF}"
- fi
-
- PARSER=/sbin/apparmor_parser
-
- # SUBDOMAIN_DIR and APPARMOR_DIR might be defined in subdomain.conf|apparmor.conf
- if [ -d "${APPARMOR_DIR}" ] ; then
- PROFILE_DIR=${APPARMOR_DIR}
- elif [ -d "${SUBDOMAIN_DIR}" ] ; then
- PROFILE_DIR=${SUBDOMAIN_DIR}
- elif [ -d /etc/apparmor.d ] ; then
- PROFILE_DIR=/etc/apparmor.d
- elif [ -d /etc/subdomain.d ] ; then
- PROFILE_DIR=/etc/subdomain.d
- fi
- ABSTRACTIONS="-I${PROFILE_DIR}"
- AA_EV_BIN=/usr/sbin/aa-eventd
- AA_EV_PIDFILE=/var/run/aa-eventd.pid
- AA_STATUS=/usr/sbin/apparmor_status
- SD_EV_BIN=/usr/sbin/sd-event-dispatch.pl
- SD_EV_PIDFILE=/var/run/sd-event-dispatch.init.pid
- SD_STATUS=/usr/sbin/subdomain_status
- SECURITYFS=/sys/kernel/security
-
- SUBDOMAINFS_MOUNTPOINT=$(grep subdomainfs /etc/fstab | \
- sed -e 's|^[[:space:]]*[^[:space:]]\+[[:space:]]\+\(/[^[:space:]]*\)[[:space:]]\+subdomainfs.*$|\1|' 2> /dev/null)
-
- if [ -d "/var/lib/${MODULE}" ] ; then
- APPARMOR_TMPDIR="/var/lib/${MODULE}"
- elif [ -d "/var/lib/${OLD_MODULE}" ] ; then
- APPARMOR_TMPDIR="/var/lib/${OLD_MODULE}"
- else
- APPARMOR_TMPDIR="/tmp"
- fi
-
-
- # keep exit status from parser during profile load. 0 is good, 1 is bad
- STATUS=0
-
- # Test if the apparmor "module" is present.
- is_apparmor_present() {
- local modules=$1
- shift
-
- while [ $# -gt 0 ] ; do
- modules="$modules|$1"
- shift
- done
-
- # check for subdomainfs version of module
- grep -qE "^($modules)[[:space:]]" /proc/modules
-
- if [ $? -ne 0 ] ; then
- ls /sys/module/apparmor 2>/dev/null | grep -qE "^($modules)"
- fi
-
- return $?
- }
-
- # This set of patterns to skip needs to be kept in sync with
- # SubDomain.pm::isSkippableFile()
- # returns 0 if profile should NOT be skipped
- # returns 1 on verbose skip
- # returns 2 on silent skip
- skip_profile() {
- local profile=$1
- if [ "${profile%.rpmnew}" != "${profile}" -o \
- "${profile%.rpmsave}" != "${profile}" -o \
- -e "${PROFILE_DIR}/disable/`basename ${profile}`" -o \
- "${profile%\~}" != "${profile}" ] ; then
- return 1
- fi
- # Silently ignore the dpkg files
- if [ "${profile%.dpkg-new}" != "${profile}" -o \
- "${profile%.dpkg-old}" != "${profile}" -o \
- "${profile%.dpkg-dist}" != "${profile}" ] ; then
- return 2
- fi
-
- return 0
- }
-
- force_complain() {
- local profile=$1
-
- # if profile not in complain mode
- if ! egrep -q "^/.*[ \t]+flags[ \t]*=[ \t]*\([ \t]*complain[ \t]*\)[ \t]+{" $profile ; then
- local link="${PROFILE_DIR}/force-complain/`basename ${profile}`"
- if [ -e "$link" ] ; then
- aa_log_warning_msg "found $link, forcing complain mode"
- return 0
- fi
- fi
-
- return 1
- }
-
- parse_profiles() {
- # get parser arg
- case "$1" in
- load)
- PARSER_ARGS="--add"
- PARSER_MSG="Loading AppArmor profiles "
- ;;
- reload)
- PARSER_ARGS="--replace"
- PARSER_MSG="Reloading AppArmor profiles "
- ;;
- *)
- aa_log_failure_msg "required 'load' or 'reload'"
- exit 1
- ;;
- esac
- aa_log_action_begin "$PARSER_MSG"
- # run the parser on all of the apparmor profiles
- if [ ! -f "$PARSER" ]; then
- aa_log_failure_msg "AppArmor parser not found"
- aa_log_action_end 1
- exit 1
- fi
-
- if [ ! -d "$PROFILE_DIR" ]; then
- aa_log_failure_msg "Profile directory not found"
- aa_log_action_end 1
- exit 1
- fi
-
- if [ -z "$(ls $PROFILE_DIR/)" ]; then
- aa_log_failure_msg "No profiles found"
- aa_log_action_end 1
- return 1
- fi
-
- for profile in $PROFILE_DIR/*; do
- skip_profile "${profile}"
- skip=$?
- # Ignore skip status == 2 (silent skip)
- if [ "$skip" -eq 1 ] ; then
- aa_log_skipped_msg "$profile"
- logger -t "AppArmor(init)" -p daemon.warn "Skipping profile $profile"
- STATUS=2
- elif [ "$skip" -ne 0 ]; then
- continue
- fi
- if [ -f "${profile}" ] ; then
- COMPLAIN=""
- if force_complain "${profile}" ; then
- COMPLAIN="-C"
- fi
- $PARSER $ABSTRACTIONS $PARSER_ARGS $COMPLAIN "$profile" > /dev/null
- if [ $? -ne 0 ]; then
- aa_log_failure_msg "$profile failed to load"
- STATUS=1
- fi
- fi
- done
- if [ $STATUS -eq 2 ]; then
- STATUS=0
- fi
- aa_log_action_end "$STATUS"
- return $STATUS
- }
-
- profiles_names_list() {
- # run the parser on all of the apparmor profiles
- TMPFILE=$1
- if [ ! -f "$PARSER" ]; then
- aa_log_failure_msg "- AppArmor parser not found"
- exit 1
- fi
-
- if [ ! -d "$PROFILE_DIR" ]; then
- aa_log_failure_msg "- Profile directory not found"
- exit 1
- fi
-
- for profile in $PROFILE_DIR/*; do
- if skip_profile "${profile}" && [ -f "${profile}" ] ; then
- LIST_ADD=$($PARSER $ABSTRACTIONS -N "$profile" | grep -v '\^')
- if [ $? -eq 0 ]; then
- echo "$LIST_ADD" >>$TMPFILE
- fi
- fi
- done
- }
-
- failstop_system() {
- level=$(runlevel | cut -d" " -f2)
- if [ $level -ne "1" ] ; then
- aa_log_failure_msg "- could not start AppArmor. Changing to runlevel 1"
- telinit 1;
- return -1;
- fi
- aa_log_failure_msg "- could not start AppArmor."
- return -1
- }
-
- module_panic() {
- # the module failed to load, determine what action should be taken
-
- case "$SUBDOMAIN_MODULE_PANIC" in
- "warn"|"WARN")
- return 1 ;;
- "panic"|"PANIC") failstop_system
- rc=$?
- return $rc ;;
- *) aa_log_failure_msg "- invalid AppArmor module fail option"
- return -1 ;;
- esac
- }
-
- is_apparmor_loaded() {
- if ! is_securityfs_mounted ; then
- mount_securityfs
- fi
-
- mount_subdomainfs
-
- if [ -f "${SECURITYFS}/${MODULE}/profiles" ]; then
- SFS_MOUNTPOINT="${SECURITYFS}/${MODULE}"
- return 0
- fi
-
- if [ -f "${SECURITYFS}/${OLD_MODULE}/profiles" ]; then
- SFS_MOUNTPOINT="${SECURITYFS}/${OLD_MODULE}"
- return 0
- fi
-
- if [ -f "${SUBDOMAINFS_MOUNTPOINT}/profiles" ]; then
- SFS_MOUNTPOINT=${SUBDOMAINFS_MOUNTPOINT}
- return 0
- fi
-
- # check for subdomainfs version of module
- is_apparmor_present apparmor subdomain
-
- return $?
- }
-
- is_securityfs_mounted() {
- grep -q securityfs /proc/filesystems && grep -q securityfs /proc/mounts
- return $?
- }
-
- mount_securityfs() {
- if grep -q securityfs /proc/filesystems ; then
- aa_action "Mounting securityfs on ${SECURITYFS}" \
- mount -t securityfs securityfs "${SECURITYFS}"
- return $?
- fi
- return 0
- }
-
-
- mount_subdomainfs() {
- # for backwords compatibility
- if grep -q subdomainfs /proc/filesystems && \
- ! grep -q subdomainfs /proc/mounts && \
- [ -n "${SUBDOMAINFS_MOUNTPOINT}" ]; then
- aa_action "Mounting subdomainfs on ${SUBDOMAINFS_MOUNTPOINT}" \
- mount "${SUBDOMAINFS_MOUNTPOINT}"
- return $?
- fi
- return 0
- }
-
- unmount_subdomainfs() {
- SUBDOMAINFS=$(grep subdomainfs /proc/mounts | cut -d" " -f2 2> /dev/null)
- if [ -n "${SUBDOMAINFS}" ]; then
- aa_action "Unmounting subdomainfs" umount ${SUBDOMAINFS}
- fi
- }
-
- load_module() {
- local rc=0
- if modinfo -F filename apparmor > /dev/null 2>&1 ; then
- MODULE=apparmor
- elif modinfo -F filename ${OLD_MODULE} > /dev/null 2>&1 ; then
- MODULE=${OLD_MODULE}
- fi
-
- if ! is_apparmor_present apparmor subdomain ; then
- aa_action "Loading AppArmor module" /sbin/modprobe -q $MODULE $1
- rc=$?
- if [ $rc -ne 0 ] ; then
- module_panic
- rc=$?
- if [ $rc -ne 0 ] ; then
- exit $rc
- fi
- fi
- fi
-
- if ! is_apparmor_loaded ; then
- return 1
- fi
-
- return $rc
- }
-
- apparmor_start() {
- aa_log_daemon_msg "Starting AppArmor"
- if ! is_apparmor_loaded ; then
- load_module
- rc=$?
- if [ $rc -ne 0 ] ; then
- aa_log_end_msg $rc
- return $rc
- fi
- fi
-
- if [ ! -w "$SFS_MOUNTPOINT/.load" ] ; then
- aa_log_failure_msg "Loading AppArmor profiles - failed, Do you have the correct privileges?"
- aa_log_end_msg 1
- return 1
- fi
-
- configure_owlsm
-
- if [ $(wc -l "$SFS_MOUNTPOINT/profiles" | awk '{print $1}') -eq 0 ] ; then
- parse_profiles load
- else
- aa_log_skipped_msg "AppArmor already loaded with profiles."
- fi
- aa_log_end_msg 0
- return 0
- }
-
- remove_profiles() {
-
- # removing profiles as we directly read from subdomainfs
- # doesn't work, since we are removing entries which screws up
- # our position. Lets hope there are never enough profiles to
- # overflow the variable
- if ! is_apparmor_loaded ; then
- aa_log_failure_msg "AppArmor module is not loaded"
- return 1
- fi
-
- if [ ! -w "$SFS_MOUNTPOINT/.remove" ] ; then
- aa_log_failure_msg "Root privileges not available"
- return 1
- fi
-
- if [ ! -x "${PARSER}" ] ; then
- aa_log_failure_msg "Unable to execute AppArmor parser"
- return 1
- fi
-
- retval=0
- #the list of profiles isn't stable once we start adding or removing
- #them so stor to tmp first
- MODULE_PLIST=$(mktemp ${APPARMOR_TMPDIR}/tmp.XXXXXXXX)
- sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | sort >"$MODULE_PLIST"
- cat "$MODULE_PLIST" | while read profile ; do
- echo -n "$profile" > "$SFS_MOUNTPOINT/.remove"
- rc=$?
- if [ ${rc} -ne 0 ] ; then
- retval=${rc}
- fi
- done
- rm "$MODULE_PLIST"
- return ${retval}
- }
-
- apparmor_stop() {
- aa_log_daemon_msg "Unloading AppArmor profiles "
- remove_profiles
- rc=$?
- log_end_msg $rc
- return $rc
- }
-
- apparmor_kill() {
- aa_log_daemon_msg "Unloading AppArmor modules "
- if ! is_apparmor_loaded ; then
- aa_log_failure_msg "AppArmor module is not loaded"
- return 1
- fi
-
- unmount_subdomainfs
- if is_apparmor_present apparmor ; then
- MODULE=apparmor
- elif is_apparmor_present subdomain ; then
- MODULE=subdomain
- else
- aa_log_failure_msg "AppArmor is builtin"
- return 1
- fi
- /sbin/modprobe -qr $MODULE
- rc=$?
- aa_log_end_msg $rc
- return $rc
- }
-
- __apparmor_restart() {
- if [ ! -w "$SFS_MOUNTPOINT/.load" ] ; then
- aa_log_failure_msg "Loading AppArmor profiles - failed, Do you have the correct privileges?"
- return 4
- fi
-
- configure_owlsm
- parse_profiles reload
- PNAMES_LIST=$(mktemp ${APPARMOR_TMPDIR}/tmp.XXXXXXXX)
- profiles_names_list ${PNAMES_LIST}
- MODULE_PLIST=$(mktemp ${APPARMOR_TMPDIR}/tmp.XXXXXXXX)
- sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | sort >"$MODULE_PLIST"
- sort "$PNAMES_LIST" | comm -2 -3 "$MODULE_PLIST" - | while read profile ; do
- echo -n "$profile" > "$SFS_MOUNTPOINT/.remove"
- done
- rm "$MODULE_PLIST"
- rm "$PNAMES_LIST"
- return 0
- }
-
- apparmor_restart() {
- if ! is_apparmor_loaded ; then
- apparmor_start
- rc=$?
- return $rc
- fi
-
- __apparmor_restart
- return $?
- }
-
- apparmor_try_restart() {
- if ! is_apparmor_loaded ; then
- return 0
- fi
-
- __apparmor_restart
- return $?
- }
-
- configure_owlsm () {
- if [ "${SUBDOMAIN_ENABLE_OWLSM}" = "yes" -a -f ${SFS_MOUNTPOINT}/control/owlsm ] ; then
- # Sigh, the "sh -c" is necessary for the SuSE aa_action
- # and it can't be abstracted out as a seperate function, as
- # that breaks under RedHat's action, which needs a
- # binary to invoke.
- aa_action "Enabling OWLSM extension" sh -c "echo -n \"1\" > \"${SFS_MOUNTPOINT}/control/owlsm\""
- elif [ -f "${SFS_MOUNTPOINT}/control/owlsm" ] ; then
- aa_action "Disabling OWLSM extension" sh -c "echo -n \"0\" > \"${SFS_MOUNTPOINT}/control/owlsm\""
- fi
- }
-
- apparmor_status () {
- if test -x ${AA_STATUS} ; then
- ${AA_STATUS} --verbose
- return $?
- fi
- if test -x ${SD_STATUS} ; then
- ${SD_STATUS} --verbose
- return $?
- fi
- if ! is_apparmor_present apparmor subdomain ; then
- echo "AppArmor is not loaded."
- rc=1
- else
- echo "AppArmor is enabled,"
- rc=0
- fi
- echo "Install the apparmor-utils package to receive more detailed"
- echo "status information here (or examine ${SFS_MOUNTPOINT} directly)."
-
- return $rc
- }
-